﻿using System;

namespace Hxsoft
{
	/// <summary>
	/// 定义一个矩形结构。
	/// </summary>
	public struct Rectangle
	{
		private double? _width;
		private double? _height;

		/// <summary>
		/// 矩形的宽度。
		/// </summary>
		public double? Width
		{
			get { return _width; }
			set { _width = value; }
		}

		/// <summary>
		/// 矩形的高度。
		/// </summary>
		public double? Height
		{
			get { return _height; }
			set { _height = value; }
		}

		/// <summary>
		/// 构造函数。
		/// </summary>
		/// <param name="width">初始宽度。</param>
		/// <param name="height">初始高度。</param>
		public Rectangle(double? width, double? height)
		{
			_width = width;
			_height = height;
		}

		/// <summary>
		/// 构造函数。
		/// </summary>
		/// <param name="rectangle">用来构造新实例的 Rectangle 对象。</param>
		public Rectangle(Rectangle rectangle)
		{
			_width = rectangle.Width;
			_height = rectangle.Height;
		}
	}

	public class RectangleOperation
	{
		#region LimitResize 在限定的范围内调整矩形尺寸
		/// <summary>
		/// 在限定的范围内调整矩形尺寸。
		/// </summary>
		/// <param name="source">要调整的矩形。</param>
		/// <param name="target">要限定的范围。</param>
		/// <param name="resizeType">调整矩形的方式。</param>
		/// <returns>调整后的矩形。</returns>
		public static Rectangle LimitResize(Rectangle source, Rectangle target, ResizeRectangleType resizeType)
		{
			Rectangle result = new Rectangle(source);

			if (resizeType == ResizeRectangleType.Compelling)
			{
				if (target.Width.HasValue)
					result.Width = target.Width.Value;
				if (target.Height.HasValue)
					result.Height = target.Height.Value;

				// 返回值
				return result;
			}

			// 以下为等比例缩放算法
			if (source.Width.HasValue && source.Height.HasValue)                // 源矩形的高和宽都定义的时候
			{
				if (target.Width.HasValue && target.Height.HasValue)              // 当同时限制宽度和高度时
				{
					if (IsNeedResize(source.Width.Value, target.Width.Value, resizeType)
						|| IsNeedResize(source.Height.Value, target.Height.Value, resizeType))               // 只要源矩形的宽或高有一项需要调整尺寸，就调整矩形尺寸
					{
						if (IsNeedResize(source.Width.Value / source.Height.Value, target.Width.Value / target.Height.Value, resizeType))
						{
							result.Width = target.Width.Value;
							result.Height = source.Height.Value / (source.Width.Value / target.Width.Value);
						}
						else
						{
							result.Height = target.Height.Value;
							result.Width = source.Width.Value / (source.Height.Value / target.Height.Value);
						}
					}
				}
				else if (target.Width.HasValue)              // 当仅限宽度时
				{
					if (IsNeedResize(source.Width.Value, target.Width.Value, resizeType))
					{
						result.Width = target.Width.Value;
						result.Height = source.Height.Value / (source.Width.Value / target.Width.Value);
					}
				}
				else if (target.Height.HasValue)             // 当仅限高度时
				{
					if (IsNeedResize(source.Height.Value, target.Height.Value, resizeType))
					{
						result.Height = target.Height.Value;
						result.Width = source.Width.Value / (source.Height.Value / target.Height.Value);
					}
				}
			}
			else if (source.Width.HasValue)               // 源矩形仅定义宽度的时候
			{
				if (target.Width.HasValue)
				{
					if (IsNeedResize(source.Width.Value, target.Width.Value, resizeType))
					{
						result.Width = target.Width.Value;
					}
				}
			}
			else if (source.Height.HasValue)              // 源矩形仅定义高度的时候
			{
				if (target.Height.HasValue)
				{
					if (IsNeedResize(source.Height.Value, target.Height.Value, resizeType))
					{
						result.Height = target.Height.Value;
					}
				}
			}

			// 返回值
			return result;
		}


		/// <summary>
		/// 在限定的范围内调整矩形尺寸。
		/// </summary>
		/// <param name="source">要调整的矩形。</param>
		/// <param name="target">要限定的范围。</param>
		/// <returns>调整后的矩形。</returns>
		public static void LimitResize(Rectangle source, Rectangle target)
		{
			LimitResize(source, target, ResizeRectangleType.ZoomOut);
		}
		#endregion




		#region IsNeedResize 根据 ResizeRectangleType 来确定是否需要调整尺寸
		/// <summary>
		/// 根据 ResizeRectangleType 来确定是否需要调整尺寸。
		/// </summary>
		/// <param name="sourceSize">源尺寸。</param>
		/// <param name="targetSize">目标尺寸。</param>
		/// <param name="resizeType">缩放方式。</param>
		/// <returns>一个布尔值表示是否需要调整尺寸。</returns>
		private static bool IsNeedResize(double sourceSize, double targetSize, ResizeRectangleType resizeType)
		{
			bool bResult = false;

			switch (resizeType)
			{
				case ResizeRectangleType.Compelling:
					if (sourceSize != targetSize)
						bResult = true;
					else
						bResult = false;
					break;
				case ResizeRectangleType.ZoomIn:
					if (sourceSize < targetSize)
						bResult = true;
					else
						bResult = false;
					break;
				case ResizeRectangleType.ZoomOut:
					if (sourceSize > targetSize)
						bResult = true;
					else
						bResult = false;
					break;
				default:
					bResult = false;
					break;
			}

			return bResult;
		}
		#endregion
	}




	/// <summary>
	/// 矩形缩放方式
	/// </summary>
	public enum ResizeRectangleType
	{
		/// <summary>
		/// 强制等比例缩放到指定的尺寸
		/// </summary>
		Compelling = 0,

		/// <summary>
		/// 等比例缩小到指定的尺寸
		/// </summary>
		ZoomOut,

		/// <summary>
		/// 等比便放大到指定的尺寸
		/// </summary>
		ZoomIn
	}
}